package com.ruoyi.wms.service;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.lang.Assert;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.ruoyi.common.core.constant.HttpStatus;
import com.ruoyi.common.core.exception.ServiceException;
import com.ruoyi.common.core.utils.MapstructUtils;
import com.ruoyi.common.mybatis.core.page.PageQuery;
import com.ruoyi.common.mybatis.core.page.TableDataInfo;
import com.ruoyi.wms.domain.bo.WarehouseRackBo;
import com.ruoyi.wms.domain.entity.WarehouseRack;
import com.ruoyi.wms.domain.vo.WarehouseRackVo;
import com.ruoyi.wms.mapper.WarehouseRackMapper;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.Objects;

/**
 * 货架Service业务层处理
 *
 * @author zcc
 * @date 2024-07-16
 */
@RequiredArgsConstructor
@Service
public class WarehouseRackService extends ServiceImpl<WarehouseRackMapper, WarehouseRack> {

    private final WarehouseRackMapper warehouseRackMapper;
    private final InventoryService inventoryService;

    /**
     * 查询货架
     */

    public WarehouseRackVo queryById(Long id) {
        return warehouseRackMapper.selectVoById(id);
    }

    /**
     * 查询货架列表
     */

    public TableDataInfo<WarehouseRackVo> queryPageList(WarehouseRackBo bo, PageQuery pageQuery) {
        LambdaQueryWrapper<WarehouseRack> lqw = buildQueryWrapper(bo);
        Page<WarehouseRackVo> result = warehouseRackMapper.selectVoPage(pageQuery.build(), lqw);
        return TableDataInfo.build(result);
    }

    /**
     * 查询货架列表
     */
    public List<WarehouseRackVo> queryList(WarehouseRackBo bo) {
        LambdaQueryWrapper<WarehouseRack> lqw = buildQueryWrapper(bo);
        return warehouseRackMapper.selectVoList(lqw);
    }

    private LambdaQueryWrapper<WarehouseRack> buildQueryWrapper(WarehouseRackBo bo) {
        Map<String, Object> params = bo.getParams();
        LambdaQueryWrapper<WarehouseRack> lqw = Wrappers.lambdaQuery();
        lqw.eq(StrUtil.isNotBlank(bo.getAreaId()), WarehouseRack::getAreaId, bo.getAreaId());
        lqw.eq(StrUtil.isNotBlank(bo.getRackCode()), WarehouseRack::getRackCode, bo.getRackCode());
        lqw.like(StrUtil.isNotBlank(bo.getRackName()), WarehouseRack::getRackName, bo.getRackName());
        lqw.orderByAsc(WarehouseRack::getOrderNum);
        return lqw;
    }

    /**
     * 新增货架
     */

    public void insertByBo(WarehouseRackBo bo) {
        validateWarehouseRackNameAndNo(bo);
        WarehouseRack add = MapstructUtils.convert(bo, WarehouseRack.class);
        add.setOrderNum(this.getNextOrderNum());
        warehouseRackMapper.insert(add);
    }

    private Long getNextOrderNum() {
        LambdaQueryWrapper<WarehouseRack> wrapper = new LambdaQueryWrapper<>();
        wrapper.orderByDesc(WarehouseRack::getOrderNum);
        wrapper.last("limit 1");
        WarehouseRack WarehouseRack = warehouseRackMapper.selectOne(wrapper);
        return WarehouseRack == null ? 0L : WarehouseRack.getOrderNum() + 1;
    }

    /**
     * 修改货架
     */

    public void updateByBo(WarehouseRackBo bo) {
        validateWarehouseRackNameAndNo(bo);
        WarehouseRack update = MapstructUtils.convert(bo, WarehouseRack.class);
        warehouseRackMapper.updateById(update);
    }

    private void validateWarehouseRackNameAndNo(WarehouseRackBo warehouseRackBo) {
        LambdaQueryWrapper<WarehouseRack> queryWrapper = Wrappers.lambdaQuery();
        queryWrapper.eq(WarehouseRack::getRackName, warehouseRackBo.getRackName()).or().eq(StrUtil.isNotBlank(warehouseRackBo.getRackCode()), WarehouseRack::getRackCode, warehouseRackBo.getRackCode());
        List<WarehouseRack> warehouseList = warehouseRackMapper.selectList(queryWrapper);
        boolean validateNameResult = warehouseList.stream().anyMatch(
            it -> Objects.equals(it.getRackName(), warehouseRackBo.getRackName()) && !Objects.equals(it.getId(), warehouseRackBo.getId()));
        Assert.isFalse(validateNameResult, "货架名称重复");
        boolean validateNoResult = warehouseList.stream().anyMatch(
            it -> Objects.equals(it.getRackCode(), warehouseRackBo.getRackCode()) && !Objects.equals(it.getId(), warehouseRackBo.getId()));
        Assert.isFalse(validateNoResult, "货架编号重复");
    }

    /**
     * 删除货架
     */

    public void deleteById(Long id) {
        validIdBeforeDelete(id);
        warehouseRackMapper.deleteById(id);
    }

    private void validIdBeforeDelete(Long id) {
        if (inventoryService.existsByWarehouseId(id)) {
            throw new ServiceException("删除失败", HttpStatus.CONFLICT, "该货架已有业务关联，无法删除！");
        }
    }

    /**
     * 批量删除货架
     */

    public void deleteByIds(Collection<Long> ids) {
        warehouseRackMapper.deleteBatchIds(ids);
    }

    @Transactional(rollbackFor = {Exception.class})
    public void updateOrderNum(List<WarehouseRackBo> tree) {
        if (CollUtil.isEmpty(tree)) {
            return;
        }
        List<WarehouseRack> updateList = MapstructUtils.convert(tree, WarehouseRack.class);
        for (int i = 0; i < updateList.size(); i++) {
            updateList.get(i).setOrderNum((long) i);
        }
        saveOrUpdateBatch(updateList);
    }
}
